// 什么是闭包？
// 闭包是指有权访问另一个函数作用域中的变量的函数。
// 闭包的用途有很多，比如可以读取函数内部的变量，
// 也可以在函数外部对变量进行操作，
// 还可以把函数内部变量保存到内存中，
// 等到函数执行完毕后释放内存。
// 闭包的实现方式有很多，下面介绍几种常见的闭包实现方式。


// 1. 立即执行函数
// 立即执行函数（Immediately-Invoked Function Expression，IIFE）是一种创建闭包的常用方式。
// 它通过函数表达式来创建闭包，函数表达式在定义的时候就执行，因此可以立即执行。
// 语法如下：

(function(){
  // 闭包内部代码
})();

// 2. 函数作为参数传递
// 另一种实现闭包的方式是将闭包函数作为参数传递给另一个函数。
// 这种方式的优点是可以把闭包函数的定义和使用分离开来，
// 使得代码更加清晰，更容易维护。

function createCounter(initial){
  var count = initial;
  return function(){
    return count++;
  };
}

var counter1 = createCounter(0);
var counter2 = createCounter(10);

console.log(counter1()); // 0
console.log(counter1()); // 1
console.log(counter2()); // 10
console.log(counter2()); // 11

// 3. 闭包的作用域
// 闭包的作用域有两种，全局作用域和函数作用域。
// 全局作用域指的是函数定义的位置，在函数外部无法访问函数内部的变量。
// 函数作用域指的是函数内部定义的变量，可以在函数内部访问。


// 4. 闭包的内存管理
// 闭包的内存管理是个复杂的过程，因为它涉及到函数执行完毕后释放内存的问题。
// 一般情况下，闭包的内存管理是由垃圾回收机制来完成的，
// 但有时为了提高性能，也可以手动管理内存。
// 手动管理内存的方法有两种，一种是将闭包函数的定义在外部，另一种是使用setTimeout来延迟执行。


// 5. 闭包的缺点
// 闭包的缺点主要有两个，一是它会占用更多的内存，二是它会增大程序运行时的开销。
// 因此，在一些要求高性能的场景下，不能滥用闭包，否则会造成程序运行效率的降低。